进程和线程的比较
6年前
840
1
在理解进程和线程概念之前首选要对并发有一定的感性认识,如果服务器同一时间内只能服务于一个客户端,其他客户端都再那里傻等的话,可见其性能的低下估计会被客户骂出翔来,因此并发编程应运而生,并发是网络编程中必须考虑的问题。
定义
进程:是程序运行的实例,是系统进行资源分配和调度的一个独立单位,它包括独立的地址空间,资源以及1个或多个线程.
进程相关文章:php多进程总结
线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
线程就是把一个进程分为很多片,每一片都可以是一个独立的流程。这已经明显不同于多进程了,进程是一个拷贝的 流程,而线程只是把一条河流截成很多条小溪。它没有拷贝这些额外的开销,但是仅仅是现存的一条河流,就被多线程技术几乎无开销地转成很多条小流程,它的伟大就在于它少之又少的系统开销。
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
为什么会有线程?
每个进程都有自己的地址空间,即进程空间,在网络或多用户换机下,一个服务器通常需要接收大量不确定数量用户的并发请求,为每一个请求都创建一个进程显然行不通(系统开销大响应用户请求效率低),因此操作系统中线程概念被引进。
- 线程的执行过程是线性的,尽管中间会发生中断或者暂停,但是进程所拥有的资源只为改线状执行过程服务,一旦发生线程切换,这些资源需要被保护起来。
- 进程分为单线程进程和多线程进程,单线程进程宏观来看也是线性执行过程,微观上只有单一的执行过程。多线程进程宏观是线性的,微观上多个执行操作。
线程的改变只代表CPU的执行过程的改变,而没有发生进程所拥有的资源的变化。
区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
维度 | 多进程 | 多线程 |
---|---|---|
数据共享、同步 | 数据共享复杂,需要用IPC;数据是分开的,同步简单 | 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 |
内存、CPU | 占用内存多,切换复杂,CPU利用率低 | 占用内存少,切换简单,CPU利用率高 |
创建销毁、切换 | 创建销毁、切换复杂,速度慢 | 创建销毁、切换简单,速度很快 |
编程、调试 | 编程简单,调试简单 | 一个线程挂掉将导致整个进程挂掉 |
分布式 | 适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单 | 适应于多核分布式 |
可靠性 | 进程间不会互相影响 | 一个线程挂掉将导致整个进程挂掉 |
执行过程 | 每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口 | 线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 |
地址空间 | 进程之间是独立的地址空间 | 同一进程的线程共享本进程的地址空间 |
一个程序至少有一个进程,一个进程至少有一个线程.
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
优缺点
线程执行开销小,但是不利于资源的管理和保护。线程适合在SMP机器(双CPU系统)上运行。
进程执行开销大,但是能够很好的进行资源管理和保护。进程可以跨机器迁移。
从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。
适用场景
使用多进程:
- 对资源的管理和保护要求高,不限制开销和效率时
使用多线程:
- 对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
- 进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。
- 需要频繁创建销毁的优先用线程,这种原则最常见的应用就是Web服务器了,来一个连接建立一个线程,断了就销毁线程,要是用进程,创建和销毁的代价是很难承受的
- 需要进行大量计算的优先使用线程。所谓大量计算,当然就是要耗费很多CPU,切换频繁了,这种情况下线程是最合适的。这种原则最常见的是图像处理、算法处理。
- 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。
代码
PHP实现多进程并行操作(可做守护进程)
/**
* 入口函数
* 将此文件保存为 ProcessOpera.php
* 在terminal中运行 /usr/local/php/bin/php ProcessOpera.php &
* 查看进程 ps aux|grep php
*/
ProcessOpera("runCode", array(), 8);
/**
* run Code
*/
function runCode($opt = array()) {
//需要在守护进程中运行的代码
}
/**
* $func为子进程执行具体事物的函数名称
* $opt为$func的参数 数组形式
* $pNum 为fork的子进程数量
*/
function ProcessOpera($func, $opts = array(), $pNum = 1) {
while(true) {
$pid = pcntl_fork();
if($pid == -1) {
exit("pid fork error");
}
if($pid) {
static $execute = 0;
$execute++;
if($execute >= $pNum) {
pcntl_wait($status);
$execute--;
}
} else {
while(true) {
//somecode
$func($opts);
sleep(1);
}
exit(0);
}
}
}
PHP实现多线程操作
class My extends Thread {
protected $name;
public $runing;
function __construct($name){
$this->runing=1;
$this->param=0;
$this->name=$name;
}
public function run() {
while($this->runing){
if($this->param){
$time=rand(1,5);
echo 'I am thread '.$this->name.',pid: '.$this->getCreatorId().",param: {$this->param},need {$time}s\n";
sleep($time);
$this->param=0;
}else{
echo "Thread {$this->name} waiting...\n";
}
sleep(1);
}
}
}
$pool=array();
$pool[]=new My('a');
$pool[]=new My('b');
$pool[]=new My('c');
//开启所有线程
foreach ($pool as $w) {
$w->start();
}
//派发任务
unset($w);
for($i=1;$i<10;$i++){
$woker_content=$i;
while(1){
foreach($pool as $w){
if(!$w->param){
$w->param=$woker_content;
echo "Thread {$w->name} empty,put param {$woker_content}.\n";
break 2;
}
}
sleep(1);
}
}
unset($w);
while(count($pool)){
foreach ($pool as $k => $w) {
if(!$w->param){
$w->runing=false;
unset($pool[$k]);
echo "Thread {$w->name} end,exit!\n";
}
}
sleep(1);
}
echo 'All thread end!';
参考文献: